package pl.edu.agh.neural.core;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class InputLayer implements ILayer
{

    private double[] values;
    private List<InputNeuron> neurons;
    private Boolean hasBias;

    public InputLayer(List<InputNeuron> neurons, boolean hasBias)
    {
        this.neurons = new ArrayList<>(neurons);
        this.hasBias = hasBias;
        if (hasBias)
        {
            InputNeuron biasNeuron = new InputNeuron();
            biasNeuron.setInputValue(1.0);
            this.neurons.add(biasNeuron);
        }
        normalize(this.neurons);
    }

    private void normalize(List<InputNeuron> neurons)
    {
//        double sum = 0;
//        for (InputNeuron neuron : neurons)
//        {
//            sum += neuron.getValue()*neuron.getValue();
//        }
//
//        double len = Math.sqrt(sum);
//        if (len > 0.0) {
//            for (InputNeuron neuron : neurons)
//            {
//                neuron.setInputValue(neuron.getValue() / len);
//            }
//        }

    }

    public int getInputVectorSize()
    {
        return hasBias ? neurons.size() - 1 : neurons.size();
    }

    @Override
    public List<? extends INeuron> getNeurons()
    {
        return neurons;
    }

    public void setValues(double[] values)
    {
        int valuesSize = values.length;
        int neuronsSize = getInputVectorSize();
        if (valuesSize != neuronsSize)
        {
            throw new RuntimeException(
                    String.format(
                            "Values vector size: %d is not equal to number of neurons: %d", valuesSize, neuronsSize));
        }

        for (int i = 0; i < valuesSize; i++)
        {
            neurons.get(i).setInputValue(values[i]);
        }
        if (hasBias)
        {
            neurons.get(valuesSize).setInputValue(1.0);
        }

        this.values = Arrays.copyOf(values, valuesSize);
        normalize(neurons);
    }

    @Override
    public double[] evaluate()
    {
        return values;
    }
}
